#include "mainwindow.h"
#include "mypacketmodel.h"
#include <deque>

extern std::deque<PPACKET> bufferDeque;

extern HANDLE hMutex;
extern bool stopThreads;

///////////////////////////////////////////////////////////////////////
//// Dirty, temporary

#include <QDebug>
#define cout qDebug()

///////////////////////////////////////////////////////////////////////

HANDLE CompletionPort;


#define PACKS_NUMBER 16


DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
	HANDLE hDevice;
	DWORD BytesTransferred;	
	PPACKET newPacket, firstPacket, currPacket;
	PHANDLE_DATA pHandleData;
	DWORD dwWaitResult, i;

	if ((pHandleData = (PHANDLE_DATA) GlobalAlloc(GPTR,sizeof(HANDLE_DATA))) == NULL)
		cout<<("GlobalAlloc() error %d\n", GetLastError());

	if ((firstPacket = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
		cout<<("GlobalAlloc() error %d\n", GetLastError());
	ZeroMemory(&(firstPacket->Overlapped), sizeof(OVERLAPPED));

	firstPacket->pNext = firstPacket;
	currPacket = firstPacket;	

	for (i=0; i<PACKS_NUMBER; ++i)
	{
		if ((newPacket = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
			cout<<("GlobalAlloc() error %d\n", GetLastError());
		ZeroMemory(&(newPacket->Overlapped), sizeof(OVERLAPPED));

		newPacket->pNext = currPacket->pNext;
		newPacket->pPrev = currPacket;

		currPacket->pNext = newPacket;

		currPacket = newPacket;
	}
	firstPacket->pPrev = currPacket;

	if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1)) == NULL)
	{
		cout<<( "Error CreateIoCompletionPort: %d\n", GetLastError());
		return 0;
	}
	hDevice = CreateFile(L"\\\\.\\CtrlUsbSniffer", 0, NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

	if(hDevice == INVALID_HANDLE_VALUE)
	{
		cout<<"fuck";
	}

	if (CreateIoCompletionPort(hDevice, CompletionPort, (ULONG_PTR)pHandleData, 1) == NULL)
	{
		cout<<("CreateIoCompletionPort Error %d\n", GetLastError());
	}

	currPacket = firstPacket;
	while (currPacket != firstPacket->pPrev)
	{
		DeviceIoControl(hDevice, IOCTL_SET_TRANSPORT_PACKET, NULL, 0, currPacket->Buffer, SIZE_OF_PACKET, 
			NULL, &(currPacket->Overlapped));
		currPacket = currPacket->pNext;
	}

	currPacket = firstPacket;
	while(true)
	{
		dwWaitResult = WaitForSingleObject(hMutex, 5000L);
			if (dwWaitResult == WAIT_TIMEOUT)
			{
				return 1;
			}
			if (stopThreads)
			{
				break;
			}
		ReleaseMutex(hMutex);

		if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred,
			(LPDWORD)&pHandleData, (LPOVERLAPPED *) &currPacket, INFINITE) == 0)
		{
			cout<<("GetQueuedCompletionStatus error! %d!\n", GetLastError());
			continue;
		}

		DeviceIoControl(hDevice, IOCTL_SET_TRANSPORT_PACKET, NULL, 0, currPacket->pPrev->Buffer, SIZE_OF_PACKET, 
			NULL, &(currPacket->pPrev->Overlapped));

		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
		if ((newPacket = (PPACKET) GlobalAlloc(GPTR,sizeof(PACKET))) == NULL)
			cout<<("GlobalAlloc() error %d\n", GetLastError());
		ZeroMemory(&(newPacket->Overlapped), sizeof(OVERLAPPED));

		newPacket->pNext = currPacket->pNext;
		newPacket->pPrev = currPacket->pPrev;	

		currPacket->pNext->pPrev = newPacket;
		currPacket->pPrev->pNext = newPacket;

		dwWaitResult = WaitForSingleObject(hMutex, 5000L);
			if (dwWaitResult == WAIT_TIMEOUT)
			{
				return 1;
			}
			bufferDeque.push_back(currPacket);			
		ReleaseMutex(hMutex);		

		currPacket = newPacket;
		currPacket = currPacket->pNext;
		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
	}

	CloseHandle(hDevice);
	//if(GlobalFree(pHandleData))
		//cout<<("GlobalFree() error %d\n", GetLastError());

	/*currPacket = firstPacket->pNext;
	PPACKET lastPacket = firstPacket->pPrev;
 	while (currPacket != lastPacket)
 	{
 		if(GlobalFree(currPacket->pPrev))
 			cout<<("GlobalFree() error %d\n", GetLastError());
		currPacket = currPacket->pNext;
 	}
	if(GlobalFree(currPacket))
		cout<<("GlobalFree() error %d\n", GetLastError());*/

	return 0;
}